/**
 * Copyright &copy; 2012-2014 <a href="https://github.cn.apestar">JeeSite</a> All rights reserved.
 */
package cn.apestar.modules.sys.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;

import cn.apestar.common.exception.BaseException;
import cn.apestar.common.service.BaseService;
import cn.apestar.common.utils.CacheUtils;
import cn.apestar.common.utils.SpringContextHolder;
import cn.apestar.common.utils.StringUtils;
import cn.apestar.modules.sys.component.UserTranslate;
import cn.apestar.modules.sys.dao.AreaDao;
import cn.apestar.modules.sys.dao.MenuDao;
import cn.apestar.modules.sys.dao.OfficeDao;
import cn.apestar.modules.sys.dao.RoleDao;
import cn.apestar.modules.sys.dao.UserDao;
import cn.apestar.modules.sys.entity.Area;
import cn.apestar.modules.sys.entity.Menu;
import cn.apestar.modules.sys.entity.Office;
import cn.apestar.modules.sys.entity.Role;
import cn.apestar.modules.sys.entity.User;
import cn.apestar.modules.sys.security.SystemAuthorizingRealm.Principal;

/**
 * 用户工具类
 * @author ThinkGem
 * @version 2013-12-05
 */
public class UserUtils {

    private static UserDao userDao = SpringContextHolder.getBean(UserDao.class);

    private static RoleDao roleDao = SpringContextHolder.getBean(RoleDao.class);

    private static MenuDao menuDao = SpringContextHolder.getBean(MenuDao.class);

    private static AreaDao areaDao = SpringContextHolder.getBean(AreaDao.class);

    private static OfficeDao officeDao = SpringContextHolder.getBean(OfficeDao.class);

    public static final String USER_CACHE = "userCache";

    public static final String USER_CACHE_ID_ = "id_";

    public static final String USER_CACHE_LOGIN_NAME_ = "ln";

    public static final String USER_CACHE_LIST_BY_OFFICE_ID_ = "oid_";

    public static final String CACHE_ROLE_LIST = "roleList";

    public static final String CACHE_MENU_LIST = "menuList";

    public static final String CACHE_AREA_LIST = "areaList";

    public static final String CACHE_MAP_LIST = "getAll";

    public static final String CACHE_OFFICE_LIST = "officeList";

    public static final String CACHE_OFFICE_ALL_LIST = "officeAllList";

    public static final String CACHE_SHANGQUAN_LIST = "shangquanList";

    /**
     * 根据ID获取用户
     * @param id
     * @return 取不到返回null
     */
    public static User get(String id) {
        User user = (User) CacheUtils.get(USER_CACHE, USER_CACHE_ID_ + id);
        if (user == null) {
            user = userDao.get(id);
            user = UserTranslate.translateUser(user);
            CacheUtils.put(USER_CACHE, USER_CACHE_ID_ + id, user);
        }
        return user;
    }

    /**
     * 清除指定用户缓存
     * @param user
     */
    public static void clearCache(User user) {
        CacheUtils.remove(USER_CACHE, USER_CACHE_ID_ + user.getId());
        CacheUtils.remove(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getLoginName());
    }

    /**
     * 根据登录名获取用户
     * @param loginName
     * @return 取不到返回null
     */
    public static User getByLoginName(String loginName, String type) {
        User user = (User) CacheUtils.get(USER_CACHE, USER_CACHE_LOGIN_NAME_ + loginName);
        if (user == null) {
            user = userDao.getByLoginName(new User(null, loginName));
            if (user == null) {
                return null;
            }
            user.setRoleList(roleDao.findList(new Role(user)));
            CacheUtils.put(USER_CACHE, USER_CACHE_ID_ + user.getId(), user);
            CacheUtils.put(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getLoginName(), user);
        }
        return user;
    }

    /**
     * 清除当前用户缓存
     */
    public static void clearCache() {
        removeCache(CACHE_ROLE_LIST);
        removeCache(CACHE_MENU_LIST);
        removeCache(CACHE_AREA_LIST);
        removeCache(CACHE_OFFICE_LIST);
        removeCache(CACHE_OFFICE_ALL_LIST);
        UserUtils.clearCache(getUser());
    }

    /**
     * 获取当前用户授权的区域
     * @return
     */
    public static List<Area> getShangQuanList() {
        @SuppressWarnings("unchecked")
        List<Area> areaList = (List<Area>) CacheUtils.get(CacheUtils.SYS_AREA, CACHE_SHANGQUAN_LIST);
        if (areaList == null) {
            areaList = areaDao.getShangQuanList(new Area());
            CacheUtils.put(CacheUtils.SYS_AREA, CACHE_SHANGQUAN_LIST, areaList);
        }
        return areaList;
    }

    /**
     * 获取当前用户
     * @return 取不到返回 new User()
     */
    public static User getUser() {
        Principal principal = getPrincipal();
        if (principal != null) {
            User user = get(principal.getId());
            if (user != null) {
                return user;
            }
            throw new BaseException("403", "登录已经失效，请重新登录");
        }
        throw new BaseException("403", "登录已经失效，请重新登录");
        // 如果没有登录，则返回实例化空的User对象。
    }

    /**
     * 获取当前用户
     * @return 取不到返回 new User()
     */
    public static User getUserNullException() {
        Principal principal = getPrincipal();
        if (principal != null) {
            User user = get(principal.getId());
            if (user != null) {
                return null;
            }
            return null;
        }
        return null;
    }

    /**
     * 获取当前用户角色列表
     * @return
     */
    public static List<Role> getRoleList() {
        @SuppressWarnings("unchecked")
        List<Role> roleList = (List<Role>) getCache(CACHE_ROLE_LIST);
        if (roleList == null) {
            User user = getUser();
            if (user.isAdmin()) {
                roleList = roleDao.findAllList(new Role());
            } else {
                Role role = new Role();
                role.getSqlMap().put("dsf", BaseService.dataScopeFilter(user.getCurrentUser(), "o", "u"));
                roleList = roleDao.findList(role);
            }
            putCache(CACHE_ROLE_LIST, roleList);
        }
        return roleList;
    }

    /**
     * 获取当前用户授权菜单
     * @return
     */
    public static List<Menu> getMenuList() {
        @SuppressWarnings("unchecked")
        List<Menu> menuList = (List<Menu>) getCache(CACHE_MENU_LIST);
        if (menuList == null || menuList.size() == 0) {
            User user = getUser();
            if (user.isAdmin()) {
                menuList = menuDao.findAllList(new Menu());
            } else {
                Menu m = new Menu();
                m.setUserId(user.getId());
                menuList = menuDao.findByUserId(m);
            }
            putCache(CACHE_MENU_LIST, menuList);
        }
        return menuList;
    }

    /**
     * 获取当前用户授权的区域
     * @return
     */
    public static List<Area> getAreaList() {
        @SuppressWarnings("unchecked")
        List<Area> areaList = areaDao.findAllList(new Area());
        return areaList;
    }

    /**
     * 获取当前用户授权的区域
     * @return
     */
    public static List<Area> getAreaList(Area area, String key) {
        @SuppressWarnings("unchecked")
        List<Area> areaList = (List<Area>) CacheUtils.get(CacheUtils.SYS_AREA, CACHE_AREA_LIST + key);
        if (areaList == null) {
            areaList = areaDao.findAllList(area);
            CacheUtils.put(CacheUtils.SYS_AREA, CACHE_AREA_LIST + key, areaList);
        }
        return areaList;
    }

    /**
     * 获取当前用户授权的区域
     * @return
     */
    public static List<Area> getAreaByLevel(String level, String key, String parentId) {
        @SuppressWarnings("unchecked")
        String keys = CACHE_AREA_LIST + level + key + parentId;
        List<Area> areaList = (List<Area>) CacheUtils.get(CacheUtils.SYS_AREA, keys);
        if (areaList == null) {
            Area area = new Area();
            area.setType(level);
            if (!StringUtils.isEmpty(key)) {
                area.setName(key);
            }
            if (!StringUtils.isEmpty(parentId)) {
                area.setParentId(parentId);
            }
            areaList = areaDao.findAllList(area);
            CacheUtils.put(CacheUtils.SYS_AREA, keys, areaList);
        }
        return areaList;
    }

    public static String getAreaId(String areaName) {
        if (areaName == null || areaName.isEmpty()) {
            return "";
        }
        return areaDao.getAreaId(areaName);
    }

    /**
     * 获取查询用户的区域
     * @return
     */
    public static List<HashMap> getALL(Map area, String key, String parentId) {
        @SuppressWarnings("unchecked")
        List<HashMap> areaList = (List<HashMap>) CacheUtils.get(CACHE_MAP_LIST + key + parentId);
        if (areaList == null) {
            if (area == null)
                area = new HashMap();
            areaList = areaDao.findAllListByMap(area);
            CacheUtils.put(CACHE_MAP_LIST + key, areaList);
        }
        return areaList;
    }

    /**
     * 获取当前用户有权限访问的部门
     * @return
     */
    public static List<Office> getOfficeList() {
        @SuppressWarnings("unchecked")
        List<Office> officeList = (List<Office>) getCache(CACHE_OFFICE_LIST);
        if (officeList == null) {
            User user = getUser();
            if (user.isAdmin()) {
                officeList = officeDao.findAllList(new Office());
            } else {
                Office office = new Office();
                office.getSqlMap().put("dsf", BaseService.dataScopeFilter(user, "a", ""));
                officeList = officeDao.findList(office);
            }
            putCache(CACHE_OFFICE_LIST, officeList);
        }
        return officeList;
    }

    /**
     * 获取当前用户有权限访问的部门
     * @return
     */
    public static List<Office> getOfficeAllList() {
        @SuppressWarnings("unchecked")
        List<Office> officeList = (List<Office>) getCache(CACHE_OFFICE_ALL_LIST);
        if (officeList == null) {
            officeList = officeDao.findAllList(new Office());
        }
        return officeList;
    }

    /**
     * 获取授权主要对象
     */
    public static Subject getSubject() {
        return SecurityUtils.getSubject();
    }

    /**
     * 获取当前登录者对象
     */
    public static Principal getPrincipal() {
        try {
            Subject subject = SecurityUtils.getSubject();
            Principal principal = (Principal) subject.getPrincipal();
            if (principal != null) {
                return principal;
            }
            // subject.logout();
        } catch (UnavailableSecurityManagerException e) {

        } catch (InvalidSessionException e) {

        }
        return null;
    }

    public static Session getSession() {
        try {
            Subject subject = SecurityUtils.getSubject();
            Session session = subject.getSession(false);
            if (session == null) {
                session = subject.getSession();
            }
            if (session != null) {
                return session;
            }
            // subject.logout();
        } catch (InvalidSessionException e) {

        }
        return null;
    }

    // ============== User Cache ==============

    public static Object getCache(String key) {
        return getCache(key, null);
    }

    public static Object getCache(String key, Object defaultValue) {
        // Object obj = getCacheMap().get(key);
        Object obj = getSession().getAttribute(key);
        return obj == null ? defaultValue : obj;
    }

    public static void putCache(String key, Object value) {
        // getCacheMap().put(key, value);
        getSession().setAttribute(key, value);
    }

    public static void removeCache(String key) {
        // getCacheMap().remove(key);
        getSession().removeAttribute(key);
    }

    /**
     * 获取年度
     * @return
     */
    public static List getBusinessYear() {
        List list = new ArrayList();
        for (int m = 0; m < 40; m++) {
            Map map = new HashMap();
            map.put("id", 1980 + m);
            list.add(map);
        }
        return list;
    }

}
